// cpplua.cpp: implementation of the cpplua class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "cpplua.h"


#pragma comment(lib,"lua5.1.lib") 
#pragma comment(lib,"lua51.lib") 
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

cpplua::cpplua():L(0)
{

}

cpplua::~cpplua()
{

}

size_t  cpplua::strlen (const char * str)
{

}
void cpplua::stackDump(lua_State* L)
{
	int i;
	int top = lua_gettop(L);
	for (i = 1; i <= top; i++)
	{
		int t = lua_type(L,i);
		switch(t)
		{
		case LUA_TSTRING :
			printf("%s",lua_tostring(L,i));
			break;
		case LUA_TBOOLEAN:
			printf(lua_toboolean(L,i) ? "true" : "false");
			break;
		case LUA_TNUMBER:
			printf("%g", lua_tonumber(L,i));
			break;
		default:
			printf("%s",lua_typename(L,t));
		}
		printf("   ");
	}
	printf("\n");
}
void cpplua::lua_interpreter(lua_State* L)
{
	char buff[256];
	int error;
	while (fgets(buff, sizeof(buff), stdin) != NULL) { 
		error = luaL_loadbuffer(L, buff, strlen(buff), 
			"line") || lua_pcall(L, 0, 0, 0); 
		if (error) { 
			fprintf(stderr, "%s", lua_tostring(L, -1)); 
			lua_pop(L, 1);/* pop error message from the stack */
		} 
	} 
}

void cpplua::loadfile(lua_State* L, char* filename)
{
	if (luaL_loadfile(L,filename) || lua_pcall(L,0,0,0))
	{
		luaL_error(L, "cannot run configuration file: %s", lua_tostring(L,-1));
	}
}

//call_va(L,"f","dd>d",x,y,&x);  //d:double i:integer s:string >:end after >: the return value
void cpplua::call_va(lua_State* L,const char* func, const char* sig, ...)
{
	va_list vl;  // typedef char* va_list;
	int narg, nres; // number of arguments and results
	
	va_start(vl,sig);
	lua_getglobal(L,func); //get function
	
	//push arguments
	narg = 0;
	while(*sig) // push
	{
		switch(*sig++)
		{
		case 'd': //double
			lua_pushnumber(L,va_arg(vl,double));
			break;
		case 'i': //int 
			lua_pushnumber(L, va_arg(vl,int));
			break;
		case 's': //string
			lua_pushstring(L,va_arg(vl,char*));
			break;
		case '>':
			goto endwhile;
		default:
			luaL_error(L, "invalid option (%c)", *(sig - 1));
			
		}
		narg++;
		luaL_checkstack(L, 1, "too many arguments"); 
	}
endwhile:
	//do the call
	nres = strlen(sig);
	if (lua_pcall(L,narg,nres,0) != 0)
	{
		luaL_error(L, "error running function `%s': %s", func, lua_tostring(L, -1)); 
	}
	
	//retrieve results
	nres = -nres;
	while(*sig)
	{
		switch (*sig++)
		{
		case 'd':
			if (!lua_isnumber(L,nres))
			{
				luaL_error(L, "wrong result type");			
			}
			*va_arg(vl,double*) =lua_tonumber(L,nres);
			break;
		case 'i':
			if (!lua_isnumber(L,nres))
			{
				luaL_error(L, "wrong result type");			
			}
			*va_arg(vl,double*) = lua_tonumber(L,nres);
			break;
		case 's':
			if (!lua_isstring(L,nres))
			{
				luaL_error(L, "wrong result type");		
			}
			*va_arg(vl,const char**) = lua_tostring(L,nres);
			break;
		default:
			luaL_error(L,"invalid option(%c)",*(sig-1));
		}
		nres++;
		
	}
	va_end(vl);
}